/**
 * Created by Administrator on 2017/1/6.
 */

var UserToken = module.exports;
require('../util/common.js');
var redis_db = require('./redis2userToken.js');

var DBFactory = require('./mysql_db');

var CONFIG = require('../config.js');
var async = require('async');

// 以下部分需要拷贝给应用服务器 -----------------------------------------

function doNothing() {}
function createTokenInfo(userInfo) {
    var ret = {
        uid:userInfo.uid,
        account:userInfo.account,
        tokenS:'TKN:' + randomString(1) + ':' + randomString(1) + ':' + randomString(1) + ':' + randomString(13),
        isAdmin:userInfo.isAdmin ? 1 : 0,
    };
    if(userInfo.app_sid){
        ret.app_sid = userInfo.app_sid;
        ret.tokenS += ':' + userInfo.app_sid;
    }
    return ret;
}

function makeKeyAcc2Token(isAdmin, account, app_sid, mainUid) {
    var keyAcc2Token = isAdmin ? 'a2tA:' : 'a2tU:';
    if(account.length > 7){
        keyAcc2Token += account.substr(0, 3) + ':' +
            account.substr(3, 2) + ':' +
            account.substr(5, 2) + ':' +
            account.substr(7);
    }
    else{
        keyAcc2Token += account;
    }
    if(app_sid){
        keyAcc2Token += ':' + app_sid;
        if(mainUid){
            keyAcc2Token += ':' + mainUid;
        }
    }
    return keyAcc2Token;
}
function decodeTokenInfo(token) {
    var pairs = token.split('_');
    if (pairs.length <= 0) {
        return {};
    }
    var ret = {tokenS:pairs[0]};
    if(pairs.length >= 2){
        ret.logIdx = pairs[1];
    }
    return ret;
}
function onLoginSaveInfo(acc2tokenKey, tkInfo, logIdx, cb) {
    var expireTime = tkInfo.isAdmin ? 1800 : 48 * 3600;
    tkInfo.renewTime = new Date().getTime();
    redis_db.set(tkInfo.tokenS, JSON.stringify(tkInfo), expireTime, function (err) {
        if (err) {
            console.log(err);
            return;
        }
    });
    redis_db.set(acc2tokenKey, tkInfo.tokenS, expireTime, function (err) {
        if (err) {
            console.log(err);
            return;
        }
    });
    var token = tkInfo.tokenS;
    if(logIdx){
        token += '_' + logIdx;
    }
    if(cb) cb(null, token, tkInfo);
}
function onLoginStep1_TokenInfo(acc2tokenKey, tkInfo, userInfo, cb) {
    if(!tkInfo){
        tkInfo = createTokenInfo(userInfo);
    }

    if (userInfo.isAdmin) {
        tkInfo.purview_Id = userInfo.purview_Id;
        tkInfo.role = userInfo.role;
    }
    else if(userInfo.app_sid){
        var logLvl = 0;

        if (userInfo.main_userInfo) {
            if(userInfo.vipInfo) tkInfo.vipInfo = userInfo.vipInfo;
            else tkInfo.vipInfo = [];

            if(userInfo.multiLogin > 0){
                if(!tkInfo.vipInfo.some(function (t) {
                        if(t.vip_sid == 'multiLogin' && !isNaN(t.lvl)){
                            logLvl = parseInt(t.lvl) + 1;
                            return true;
                        }
                        return false
                    })){
                    logLvl = 1;
                }
            }

            tkInfo.main_userInfo = userInfo.main_userInfo;
            if (userInfo.group_name) tkInfo.group_name = userInfo.group_name;
            if (userInfo.app_sid) tkInfo.app_sid = userInfo.app_sid;
            if (userInfo.sub_status) tkInfo.sub_status = userInfo.sub_status;
            if (userInfo.name) tkInfo.name = userInfo.name;
            if (userInfo.sub_auth) tkInfo.sub_auth = userInfo.sub_auth;
            if (userInfo.sub_name) tkInfo.sub_name = userInfo.sub_name;
        }
        else if(userInfo.appInfo && userInfo.appInfo.length > 0){
            tkInfo.appInfo = userInfo.appInfo;
            // var appInfo = userInfo.appInfo[0];
            // if(appInfo.vipInfo) tkInfo.vipInfo = appInfo.vipInfo;
            // else tkInfo.vipInfo = {};

            if(userInfo.multiLogin > 0){
                if(tkInfo.appInfo[0].vipInfo && tkInfo.appInfo[0].vipInfo.multiLogin && tkInfo.appInfo[0].vipInfo.multiLogin.vip_level) logLvl = tkInfo.appInfo[0].vipInfo.multiLogin.vip_level + 1;
                // if(tkInfo.vipInfo.multiLogin.vip_level) logLvl = tkInfo.vipInfo.multiLogin.vip_level + 1;
                if(!logLvl) logLvl = 1;
            }
        }
        if(logLvl > 0){
            tkInfo.logIdx = tkInfo.logIdx ? tkInfo.logIdx : 0;
            if(++tkInfo.logIdx > 99) tkInfo.logIdx = 1;
            tkInfo.logLvl = logLvl;
        }
    }
    onLoginSaveInfo(acc2tokenKey, tkInfo, tkInfo.logIdx, cb);
}
UserToken.onLogin = function (userInfo, cb) {
    var mainUid = (userInfo.main_userInfo != undefined && userInfo.main_userInfo.uid) ? userInfo.main_userInfo.uid : 0;
    var acc2tokenKey = makeKeyAcc2Token(userInfo.isAdmin, userInfo.account, userInfo.app_sid, mainUid);

    redis_db.get(acc2tokenKey, function (err, tokenS) {
        if (err) {
            console.log(err);
            cb(err);
            return;
        }
        if(!tokenS){
            onLoginStep1_TokenInfo(acc2tokenKey, null, userInfo, cb);
            return;
        }

        redis_db.get(tokenS, function (err1, result) {
            if (err1) {
                console.log(err1);
                cb(err1);
                return;
            }
            if(!result){
                redis_db.del(tokenS, doNothing);
                onLoginStep1_TokenInfo(acc2tokenKey, null, userInfo, cb);
                return;
            }

            var tkInfo = JSON.parse(result);
            onLoginStep1_TokenInfo(acc2tokenKey, tkInfo, userInfo, cb);
            return;
        });
    });
};

UserToken.checkLogin = function (tokenCpx, cb) {
    if (!tokenCpx) {
        cb(null, false);
    }
    else {
        var tokenInput = decodeTokenInfo(tokenCpx);

        redis_db.get(tokenInput.tokenS, function (err, result) {
            if (err) {
                cb(err);
                return;
            }
            if (result) {
                var tkInfo = JSON.parse(result);

                if(!tkInfo || (tkInfo.app_sid !='*' && CONFIG && CONFIG.appSid && CONFIG.appSid != 'common' && CONFIG.appSid != tkInfo.app_sid)){
                    cb(null, false, '尚未登陆本应用!');
                    return;
                }
                if(!tkInfo.isAdmin){
                    if(tokenInput.logIdx > 0 && tkInfo.logIdx){
                        var logIdx = tokenInput.logIdx;
                        var logLvl = tkInfo.logLvl ? tkInfo.logLvl : 1;
                        if((logIdx > tkInfo.logIdx && logIdx <= tkInfo.logIdx + 99 - logLvl)
                            || (logIdx < tkInfo.logIdx && logIdx <= tkInfo.logIdx - logLvl))
                        {
                            cb(null, false, '已在其他终端登陆, 此终端已离线, 请重新登陆!');
                            return;
                        }
                    }
                }
                if(tkInfo.renewTime + 90000 < new Date().getTime()){
                    var expireTime = tkInfo.isAdmin ? 1800 : 48 * 3600;
                    var mainUid = tkInfo.main_userInfo ? tkInfo.main_userInfo.uid : 0;
                    var acc2tokenKey = makeKeyAcc2Token(tkInfo.isAdmin, tkInfo.account, tkInfo.app_sid, mainUid);
                    redis_db.expire(acc2tokenKey, expireTime, doNothing);
                    redis_db.expire(tkInfo.tokenS, expireTime, doNothing);
                }
                cb(null, tkInfo);
                return;
            }
            cb(null, false);
        });
    }
};

UserToken.checkLoginByApp = function (tokenCpx, cb) {
    if (!tokenCpx) {
        cb(null, false);
    }
    else {
        var tokenInput = {tokenS:tokenCpx};
        redis_db.get(tokenInput.tokenS, function (err, result) {
            if (err) {
                cb(err);
                return;
            }
            if (result) {
                var tkInfo = JSON.parse(result);

                if(!tkInfo || (tkInfo.app_sid !='*' && CONFIG && CONFIG.appSid && CONFIG.appSid != 'common' && CONFIG.appSid != tkInfo.app_sid)){
                    cb(null, false, '尚未登陆本应用!');
                    return;
                }
                if(!tkInfo.isAdmin){
                    if(tokenInput.logIdx > 0 && tkInfo.logIdx){
                        var logIdx = tokenInput.logIdx;
                        var logLvl = tkInfo.logLvl ? tkInfo.logLvl : 1;
                        if((logIdx > tkInfo.logIdx && logIdx <= tkInfo.logIdx + 99 - logLvl)
                            || (logIdx < tkInfo.logIdx && logIdx <= tkInfo.logIdx - logLvl))
                        {
                            cb(null, false, '已在其他终端登陆, 此终端已离线, 请重新登陆!');
                            return;
                        }
                    }
                }
                if(tkInfo.renewTime + 90000 < new Date().getTime()){
                    var expireTime = tkInfo.isAdmin ? 1800 : 48 * 3600;
                    var mainUid = tkInfo.main_userInfo ? tkInfo.main_userInfo.uid : 0;
                    var acc2tokenKey = makeKeyAcc2Token(tkInfo.isAdmin, tkInfo.account, tkInfo.app_sid, mainUid);
                    redis_db.expire(acc2tokenKey, expireTime, doNothing);
                    redis_db.expire(tkInfo.tokenS, expireTime, doNothing);
                }
                cb(null, tkInfo);
                return;
            }
            cb(null, false);
        });
    }
};

//检查系统、产品管理员登录
UserToken.checkAdminLogin = function (token, appSidOrVipSid, cb) {
    var appSid = null;
    var vipSid = null;
    if (CONFIG && CONFIG.appSid && (CONFIG.appSid != 'common' && CONFIG.appSid != appSidOrVipSid)) {
        appSid = CONFIG.appSid;
        vipSid = appSidOrVipSid;
    }
    else {
        appSid = appSidOrVipSid;
        vipSid = null;
    }
    UserToken.checkAdminAllLogin(token, appSid, vipSid, cb);
    return;
};

//检查系统、产品管理员登录
UserToken.checkAdminToken = function (token, cb) {
    if (!token) {
        cb('token不为空', 400);
        return;
    }

    UserToken.checkLogin(token, function (err, adminInfo) {
        if (err) {
            cb(err, 400);
            return;
        }

        if (!adminInfo) {
            cb('请先登录', 403);
            return;
        }

        if (!adminInfo.isAdmin) {
            cb('您不是管理员！', 400);
            return;
        }
        cb(null,0,adminInfo);
        return;
    });
};

//检查系统、产品、功能管理员登录
UserToken.checkAdminAllLogin = function (token, app_sid, vip_sid, cb) {
    if (!token) {
        cb('token不为空', 400);
        return;
    }

    UserToken.checkLogin(token, function (err, adminInfo) {
        if (err) {
            cb(err, 400);
            return;
        }

        if (!adminInfo) {
            cb('请先登录', 403);
            return;
        }

        if (!adminInfo.isAdmin) {
            cb('您不是管理员！', 403);
            return;
        }

        if (adminInfo.role.indexOf('admin') >= 0) {
            cb(null, 0, adminInfo);
            return;
        }
        if (app_sid && adminInfo.role.indexOf('adm_' + app_sid) >= 0) {
            cb(null, 0, adminInfo);
            return;
        }
        if (app_sid && vip_sid && adminInfo.role.indexOf(vip_sid + '_' + app_sid) >= 0) {
            cb(null, 0, adminInfo);
            return;
        }
        cb('无权限', 400);
        return;
    });
};

//检查系统、产品、功能管理员登录
UserToken.checkAdminAllLogin = function (token, app_sid, vip_sid, cb) {
    if (!token) {
        cb('token不为空', 400);
        return;
    }

    UserToken.checkLogin(token, function (err, adminInfo) {
        if (err) {
            cb(err, 400);
            return;
        }

        if (!adminInfo) {
            cb('请先登录', 403);
            return;
        }

        if (!adminInfo.isAdmin) {
            cb('您不是管理员！', 403);
            return;
        }

        if (adminInfo.role.indexOf('admin') >= 0) {
            cb(null, 0, adminInfo);
            return;
        }
        if (app_sid && adminInfo.role.indexOf('adm_' + app_sid) >= 0) {
            cb(null, 0, adminInfo);
            return;
        }
        if (app_sid && vip_sid && adminInfo.role.indexOf(vip_sid + '_' + app_sid) >= 0) {
            cb(null, 0, adminInfo);
            return;
        }
        cb('无权限', 400);
        return;
    });
};

//检查用户登录、token且返回错误的
// cb(err,errCode,UserInfo)
UserToken.checkUserLogin = function (token, cb) {
    if (!token) {
        cb('token不为空', 400);
        return;
    }
    UserToken.checkLogin(token, function (err, userInfo) {
        if (err) {
            cb(err, 400);
            return;
        }
        if (!userInfo || userInfo.isAdmin) {
            cb('请先登录', 403);
            return;
        }
        cb(null, 0, userInfo);
    });
};

//检查用户或管理员登录、token且返回错误的
// cb(err,errCode,UserInfo)
UserToken.checkAllLogin = function (token, identify, cb) {
    if (!token) {
        cb('token不为空', 400);
        return;
    }
    UserToken.checkLogin(token, function (err, userInfo) {
        if (err) {
            cb(err, 400);
            return;
        }
        if (!userInfo) {
            cb('请先登录', 403);
            return;
        }
        if (userInfo.isAdmin) {
            if (userInfo.role.indexOf('admin') < 0 && userInfo.role.indexOf('adm_paodan') < 0 && userInfo.role.indexOf(identify+'_paodan') < 0) {
                cb('无权限', 400);
                return;
            }
        }
        cb(null, 0, userInfo);
    });
};

UserToken.acc2uToken = function (par,cb) {
    var acc2tokenKey = makeKeyAcc2Token(false, par.account, par.app_key, null);
    redis_db.get(acc2tokenKey, function (err, tokenS) {
        if (err) {
            return;
        }
        cb(null, tokenS);
        return;
    });
};
UserToken.delUserToken = delUserToken;

//修改密码后生成新的token
UserToken.updateToToken = function (userInfo, cb) {
    var acc2tokenKey = makeKeyAcc2Token(userInfo.isAdmin, userInfo.account, userInfo.app_sid, null);
    redis_db.keys(acc2tokenKey + '*', function (err, tokens) {
        if (!err && tokens) {
            tokens.forEach(function (token) {
                redis_db.get(token, function (err, rsp) {
                    if(!err){
                        redis_db.del(rsp, doNothing);
                    }
                });
                redis_db.del(token, doNothing);
            });
        }
        UserToken.onLogin(userInfo, cb);
    });
};

UserToken.onLogout = function (tokenCpx, cb) {
    var tokenInfo = decodeTokenInfo(tokenCpx);
    redis_db.get(tokenInfo.tokenS, function (err, rsp) {
        if(!err){
            redis_db.del(rsp, doNothing);
        }
    });
    redis_db.del(tokenInfo.tokenS, doNothing);
    cb(null);
};

// 以下部分不需要拷贝给应用服务器 ------------------------------到此结束

//改变子账号信息后，需调用该方法，将目前子账号token给下了

// sub_uid: 子账号
// uid: 主账号
// app_sid：产品
function delUserToken(acc, app_sid, mainUid) {
    var acc2tokenKey = makeKeyAcc2Token(false, acc, app_sid, mainUid);
    redis_db.get(acc2tokenKey, function (err, tokenS) {
        if (err) {
            return;
        }
        redis_db.del(acc2tokenKey, doNothing);
        if(tokenS)redis_db.del(tokenS, doNothing);
    });
}
UserToken.delSubToken = function (data, cb) {
    //主账号
    if (!data.uid) {
        cb('uid为空');
        return;
    }
    //产品
    if (!data.app_sid) {
        cb('app_sid为空');
        return;
    }
    //子账号
    if (!data.sub_account) {
        cb('sub_account为空');
        return;
    }
    delUserToken(data.sub_account, data.app_sid, data.uid);
    cb(null, null);
};

// data : uid、app_sid(选)(没有，默认是所有产品下的子账号都会改)
//删除主账号旗下的在线子账号token(用于修改子账号)
//
UserToken.delSubs = function (data, cb) {
    //主账号
    if (!data.uid) {
        cb('uid为空');
        return;
    }
    //app_sid
    // if (!data.app_sid) {
    //     cb('app_sid为空');
    //     return;
    // }

    async.waterfall([
            function (callback) {
                //查出主账号旗下的子uid
                var sql = 'select b.account from user_subaccount a left join users b on b.uid = a.sub_uid where a.uid = ? ';
                var sqlValue = [data.uid];
                if(data.app_sid){
                    sql += ' and a.app_sid = ?';
                    // sqlValue.push(DBFactory.escape(data.app_sid));
                    sqlValue.push("paodan");
                }
                DBFactory.poolQuery(sql,sqlValue,
                    function () {
                        cb('no connection');
                    },
                    function(err, result){
                        if(err){
                            cb(err);
                            console.log(err);
                            return;
                        }
                        console.log(result);
                        callback(null,result);
                    }
                );
            },
            function (subAccounts,callback) {
                if(subAccounts && subAccounts.length > 0){
                    subAccounts.forEach(function (acc) {
                        delUserToken(acc, data.app_sid, data.uid);
                    });
                    callback(null, null);
                }else {
                    callback(null,null);
                }
            },
        ],
        function (DbErr, Info) {
            if (DbErr) {
                cb(DbErr);
            } else {
                cb(null, Info);
            }
        });

};
